#ifndef SIMPLE_IO_SOCKET_EPOLL_H
#define SIMPLE_IO_SOCKET_EPOLL_H

#include <netinet/in.h>
#include <vector>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include "spdlog/spdlog.h"
#include "socket_base.h"

namespace simple {
    class SocketEpoll : public SocketBase {
    private:
        // 监听端口
        int port_ = 8080;
        // 协议模式, 如tcp, tcp
        int socket_style_ = SOCK_STREAM;
        // 监听句柄
        int listen_fd_ = 0;
        // 监听地址
        sockaddr_in listen_addr_{};
        // 监听会话
        Session *listenSession_ = nullptr;
        // epoll句柄
        int epoll_fd_ = 0;
        // epoll就绪缓冲区大小
        int ready_event_buff_size_ = 1024;
        // epoll就绪缓冲区队列
        epoll_event *ready_event_buff_ = new struct epoll_event[ready_event_buff_size_];
        // 会话处理函数
        std::function<void(Session *)> handler_;

        /**
         * 创建socket
         */
        bool openSocket();

        /**
         * 监听socket, 绑定地址
         */
        bool openListen();

        /**
         * 创建epoll
         */
        bool openEpoll();

        /**
         * 注册监听socket的句柄
         */
        bool registerEpoll();

        /**
         * 注册指定socket句柄, 同时设置NIO非阻塞模式
         */
        bool registerEpoll(int register_fd, Session *session);

        /**
         * 注销监听的socket句柄
         */
        bool unRegisterEpoll();

        /**
         * 注销指定句柄
         */
        bool unRegister_epoll(Session *session);

        /**
         * 响应请求, 从监听socket_fd中建立新的客户端连接
         */
        void createSession();

        /**
         * 处理客户端连接
         */
        void doAccept(epoll_event epollEvent);

    public:
        explicit SocketEpoll(int port);

        SocketEpoll(int port, int socketStyle);

        void setPort(int port) noexcept override;

        void setStyle(int style) noexcept override;

        bool ready() override;

        bool accept() override;

        void setHandler(const std::function<void(Session *)> &function) override;

        void close() noexcept override;
    };
}

#endif //SIMPLE_IO_SOCKET_EPOLL_H
